Clean wrpt state when emulating CR3 write.
authorkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Wed, 1 Mar 2006 13:49:31 +0000 (14:49 +0100)
committerkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Wed, 1 Mar 2006 13:49:31 +0000 (14:49 +0100)
Signed-off-by: Keir Fraser <keir@xensource.com>
xen/arch/x86/mm.c
xen/arch/x86/traps.c
xen/include/asm-x86/mm.h

index 321d2b9deed8aa47f8d27ab13f51c6ae1040b105..1e29ce5d2d3319a60b39b26adaab20967590fefd 100644 (file)
@@ -475,7 +475,8 @@ get_page_from_l1e(
     {
         MEM_LOG("Error getting mfn %lx (pfn %lx) from L1 entry %" PRIpte
                 " for dom%d",
-                mfn, get_gpfn_from_mfn(mfn), l1e_get_intpte(l1e), d->domain_id);
+                mfn, get_gpfn_from_mfn(mfn),
+                l1e_get_intpte(l1e), d->domain_id);
     }
 
     return okay;
@@ -515,7 +516,6 @@ get_page_from_l2e(
 
 
 #if CONFIG_PAGING_LEVELS >= 3
-
 static int 
 get_page_from_l3e(
     l3_pgentry_t l3e, unsigned long pfn,
@@ -545,11 +545,9 @@ get_page_from_l3e(
 #endif
     return rc;
 }
-
 #endif /* 3 level */
 
 #if CONFIG_PAGING_LEVELS >= 4
-
 static int 
 get_page_from_l4e(
     l4_pgentry_t l4e, unsigned long pfn, 
@@ -579,7 +577,6 @@ get_page_from_l4e(
 
     return rc;
 }
-
 #endif /* 4 level */
 
 
@@ -649,28 +646,23 @@ static void put_page_from_l2e(l2_pgentry_t l2e, unsigned long pfn)
 
 
 #if CONFIG_PAGING_LEVELS >= 3
-
 static void put_page_from_l3e(l3_pgentry_t l3e, unsigned long pfn)
 {
     if ( (l3e_get_flags(l3e) & _PAGE_PRESENT) && 
          (l3e_get_pfn(l3e) != pfn) )
         put_page_and_type(mfn_to_page(l3e_get_pfn(l3e)));
 }
-
 #endif
 
 #if CONFIG_PAGING_LEVELS >= 4
-
 static void put_page_from_l4e(l4_pgentry_t l4e, unsigned long pfn)
 {
     if ( (l4e_get_flags(l4e) & _PAGE_PRESENT) && 
          (l4e_get_pfn(l4e) != pfn) )
         put_page_and_type(mfn_to_page(l4e_get_pfn(l4e)));
 }
-
 #endif
 
-
 static int alloc_l1_table(struct page_info *page)
 {
     struct domain *d = page_get_owner(page);
@@ -1569,6 +1561,8 @@ int new_guest_cr3(unsigned long mfn)
     int okay;
     unsigned long old_base_mfn;
 
+    ASSERT(writable_pagetable_in_sync(d));
+
     if ( shadow_mode_refcounts(d) )
     {
         okay = get_page_from_pagenr(mfn, d);
index 2dabc44c31b1df9863803a1a2392542fa2af91bc..97cf8bb5ab66761c1b719929c007afd58a438da9 100644 (file)
@@ -951,6 +951,7 @@ static int emulate_privileged_op(struct cpu_user_regs *regs)
             
         case 3: /* Write CR3 */
             LOCK_BIGLOCK(v->domain);
+            cleanup_writable_pagetable(v->domain);
             (void)new_guest_cr3(gmfn_to_mfn(v->domain, paddr_to_pfn(*reg)));
             UNLOCK_BIGLOCK(v->domain);
             break;
index 4d7870fb0342b4c40dbbad07a84f72dcd8ef19c9..040d919626bb0bbec08092c7ea348a028f2bcbd7 100644 (file)
@@ -337,6 +337,10 @@ void cleanup_writable_pagetable(struct domain *d);
         UNLOCK_BIGLOCK(d);                                      \
     } while ( 0 )
 
+#define writable_pagetable_in_sync(d)           \
+    (!((d)->arch.ptwr[PTWR_PT_ACTIVE].l1va |    \
+       (d)->arch.ptwr[PTWR_PT_INACTIVE].l1va))
+
 int audit_adjust_pgtables(struct domain *d, int dir, int noisy);
 
 #ifndef NDEBUG